package com.devframe.web.taglib;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;

/**
 * 
 * <pre>
 * &lt;b&gt;&lt;font color=&quot;blue&quot;&gt;SelectTag&lt;/font&gt;&lt;/b&gt;
 * </pre>
 * 
 * <pre>
 * &lt;b&gt; -根据条件进行输出，用于多数据集对应输出--&lt;/b&gt;
 * </pre>
 * <pre>
 * 支持array\Collection\Iterator
 * </pre>
 * <pre>
 * </pre>
 * 
 * JDK版本：JDK1.4
 * 
 * 
 */
public class CondOutTag extends AbstractBaseTag {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 6978778965175209962L;

    /**
     * 选项列表数据，可以是list,iterator,array,map等类型，可以使用request中的名字或者通过${}获取的对象。从其他对象的属性得到的数据需要使用EL表达式获取
     */
    private Object items;

    /**
     * name 临时存储属性名，用于需要进一步处理，暂时不输出的情况。如需要格式化
     */
    private String name;

    /**
     * 显示字段
     */
    private String valueField;

    /**
     * 条件字段
     */
    private String condField;

    /**
     * 条件值，支持EL表达式
     */
    private Object condValue;

    /**
     * defaultValue 默认值，即找不到匹配记录时的默认值
     */
    private Object defaultValue = "";

    // ////////////////////////////////////////////
    /**
     * 标签处理逻辑，
     * 
     * @return SKIP_BODY
     */
    public int doStartTag() {
        return SKIP_BODY;
    }

    /**
     * doEndTag
     * 
     * @return EVAL_PAGE
     * @throws JspException
     *             JspException
     * @see javax.servlet.jsp.tagext.BodyTagSupport#doEndTag()
     */
    public int doEndTag() throws JspException {
        try {
            if (items == null || items.equals("")) {
                return EVAL_PAGE;
            }
            Object options = items;
            if (items instanceof String) {
                // options = pageContext.findAttribute((String) items);
                options = findAttribute((String) items);
            }
            if (options == null) {
                return EVAL_PAGE;
            }
            // 符合条件的记录
            Object validObj = null;
            // 默认从pageContext中看是否有缓存，能否满足要求，以避免过多的循环查找
            validObj = pageContext.getAttribute(items.getClass().getName() + items.toString(),
                pageContext.PAGE_SCOPE);
            if (validObj == null || !this.validateCond(validObj)) {
                validObj = null;
                if (options instanceof Map) {
                    Map map = (Map) options;
                    for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
                        Map.Entry entry = (Map.Entry) i.next();
                        Object value = entry.getValue();
                        Object key = entry.getKey().toString();
                        if (this.validateCond(value)) {
                            validObj = value;
                        }
                    }
                } else if (options instanceof Iterator || options instanceof Collection) {
                    Iterator it = null;
                    if (options instanceof Iterator) {
                        it = (Iterator) options;
                    } else {
                        it = ((Collection) options).iterator();
                    }
                    while (it.hasNext()) {
                        Object entry = it.next();
                        if (this.validateCond(entry)) {
                            validObj = entry;
                        }
                    }
                } else if (options.getClass().isArray()) {// 数组

                    int length = Array.getLength(options);
                    for (int j = 0; j < length; j++) {
                        Object entry = Array.get(options, j);
                        if (this.validateCond(entry)) {
                            validObj = entry;
                        }
                    }
                }
            } else {
                // 缓存当前记录
                pageContext.setAttribute(items.getClass().getName() + items.toString(), validObj);
            }
            Object value = null;
            if (validObj != null) {
                value = this.getPropertyValue(valueField, validObj);
            }
            if (value == null) {
                value = defaultValue;
            }
            if (name != null) {
                pageContext.setAttribute(name, value);
            } else {
                JspWriter writer = null;
                try {
                    writer = this.getPreviousOut();
                } catch (Exception e1) {
                    writer = pageContext.getOut();
                }
                try {
                    writer.print(value.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return EVAL_PAGE;
        } catch (Exception e) {
            return EVAL_PAGE;
        }
    }

    /**
     * validateCond
     * 
     * @param item
     *            当前对象
     * @return 是否符合条件
     * 
     */
    private boolean validateCond(Object item) {
        if (item != null && !item.getClass().isPrimitive()) {
            Object condFieldValue = getPropertyValue(this.condField, item);
            if (condFieldValue != null && condFieldValue.equals(condValue)) {
                return true;
            }
        }
        return false;
    }

    /**
     * release
     * 
     * @see javax.servlet.jsp.tagext.BodyTagSupport#release()
     */
    public void release() {
        super.release();
    }

    public Object getItems() {
        return items;
    }

    public void setItems(Object items) {
        this.items = items;
    }

    public void setItems(String items) {
        this.items = items;
    }

    public String getValueField() {
        return valueField;
    }

    public void setValueField(String valueField) {
        this.valueField = valueField;
    }

    public String getCondField() {
        return condField;
    }

    public void setCondField(String condField) {
        this.condField = condField;
    }

    public Object getCondValue() {
        return condValue;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setCondValue(Object condValue) {
        this.condValue = condValue;
    }

    public Object getDefaultValue() {
        return defaultValue;
    }

    public void setDefaultValue(Object defaultValue) {
        this.defaultValue = defaultValue;
    }

}
